/*
 * Copyright (c) 2011, Fredrik Häggström
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Luleå University of Technology nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
/**
 * \file
 * \brief The CAN Driver header file.
 */

#ifndef CAN_H_
#define CAN_H_

#include <tT.h>
#include <env.h>

#define STANDARD		0
#define EXTENDED		1


#define CAN_STD			0
#define CAN_STD_GRP	1
#define CAN_EXT			2
#define	CAN_EXT_GRP	3


#define DATA			0
#define REMOTE			1

#define CAN_STD_ID_FORMAT (1<<31)
#define CAN_EXT_ID_FORMAT (0<<31)

#define CAN_CANOPEN (1<<30)

#define CAN_ERROR 1

typedef struct can_msg_t
{
  uint32_t id; 			/** 29 or 11 bit ID */
  uint32_t mask;		/** 29 or 11 bit mask */
  uint32_t data[2]; 		/** 8-bytes of data */	
  uint8_t len; 			/** lenth of data */
  uint8_t format; 		/** 0 = 11 bit format. 1 = 29 bit format */				
  uint8_t type; 		/** 0 = transmit. 1 = remote message */
} can_msg_t; 

typedef struct can_listner_t
{
  tt_object_t *object;
  tt_method_t method;
  uint32_t id;
  uint32_t index;
  uint32_t mask;
  struct can_listner_t *next;
  //can_msg_t msg;
  
} can_listner_t;

typedef struct can_t
{
  tt_object_t super;
  can_listner_t *listners;
  uint32_t baudrate;
  uint16_t std;
  uint16_t std_grp;
  uint16_t ext;
  uint16_t ext_grp;
  uint16_t Full_CAN;
  uint8_t  poll;
  uint32_t Rx;
  uint32_t Tx;
  uint32_t ID;
} can_t;

/* ************************************************************************** */

/**
 * \brief CAN Initalize macro.
 *
 * \param baud Baudrate for the CANbus
 */
#define can(baud) {tt_object(), NULL, baud, 0, 0, 0, 0, 0, 0, 0, 0, 112}

/* ************************************************************************** */

/**
 * \brief CAN Listner macro.
 *
 * \param obj Object preforming the method.
 * \param meth Method that will be called.
 * \param id The ID that the Listner will listen for.
 * \param format Format of the CAN message. CAN_STD_ID_FORMAT/CAN_EXT_ID_FORMAT.
 * \param index Index on the CANopen protocol. If == 0 no indexing will be preformed.
 * \param mask Mask for ID if Index == 0, else mask for Index.
 */
#define listner(obj,meth,id,format,index,mask) { (tt_object_t *)obj, (tt_method_t)meth, (id&~(1<<31))|(format&(1<<31)), index, mask}

/* ************************************************************************** */
extern can_t can;

env_result_t can_init(can_t *self, uint32_t *baudrate);
env_result_t can_send(can_t *self, can_msg_t *can_msg);
env_result_t can_installer(can_t *self, can_listner_t *listner);
env_result_t can_keep_alive( can_t *self, void *none ); 
env_result_t can_sync( can_t *self, void *none );

#endif
